package com.fadadianqi.logistics.admin.controller;

import com.fadadianqi.logistics.admin.controller.form.StoreForm;
import com.fadadianqi.logistics.admin.controller.vo.GoodsVO;
import com.fadadianqi.commons.BackToURLUtils;
import com.fadadianqi.commons.JSONProvider;
import com.fadadianqi.goods.model.*;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.logistics.inventory.model.Item;
import com.fadadianqi.logistics.inventory.service.InventoryService;
import com.fadadianqi.logistics.inventory.service.StorehouseService;
import com.fadadianqi.logistics.search.GoodsSearcher;
import com.fadadianqi.search.Result;
import com.yeqiangwei.commons.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.fadadianqi.logistics.admin.controller.URIMappingUtils.INVENTORY_PREFIX;

@Controller
@Transactional(propagation = Propagation.REQUIRED)
public class StoreController {

    private static final String VIEW_LIST = "admin/store/list";
    private static final String VIEW_FORM = "admin/store/form";
    private static final String FORM_NAME = "storeForm";
    private static final String URI_LIST = INVENTORY_PREFIX + "/store/list";
    private static final String URI_FORM = INVENTORY_PREFIX + "/store/form";
    private static final String URI_SAVE = INVENTORY_PREFIX + "/store/save";

    private static final String PARAM_GOODS_ID = "gid";
    private static final String PARAM_BRAND_ID = "bid";
    private static final String PARAM_CATEGORY_ID = "cid";
    private static final String PARAM_BACK_URL = "backURL";

    private static final int MAX_LIST = 50; // 列表最多显示的商品条数


    private static final Log LOG = LogFactory.getLog(StoreController.class);

    @RequestMapping(value = URI_FORM, method = RequestMethod.GET)
    public String form(HttpServletRequest request, ModelMap model) {
        BackToURLUtils.setParamURLToAttr(request, PARAM_BACK_URL);
        model.addAttribute("brandList", getBrandList(null));
        model.addAttribute("categoryList", getCategoryList(null));
        model.addAttribute("storehouseList", storehouseService.findAll());
        model.addAttribute(FORM_NAME, getGoodsForm(request));
        return VIEW_FORM;
    }

    @Transactional(readOnly = false, rollbackFor = RuntimeException.class)
    @RequestMapping(value = URI_SAVE, method = RequestMethod.POST)
    public String save(@ModelAttribute(FORM_NAME) StoreForm form,
                       BindingResult result, SessionStatus status,
                       HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {

        if (ValidatorHelper.isEmpty(form.getStorehouseId())) {
            form.setStorehouseId(null);
        }

        if (ValidatorHelper.isEmpty(form.getId())
                || ValidatorHelper.isEmpty(form.getBrandId())
                || ValidatorHelper.isEmpty(form.getCategoryId())) {
            result.reject("remind.illegal.parameters");
        }

        if (result.hasErrors()) {
            model.addAttribute("brandList", getBrandList(null));
            model.addAttribute("categoryList", getCategoryList(null));
            model.addAttribute(FORM_NAME, getGoodsForm(request));
            return VIEW_FORM;
        }

        // 保存条目
        int count = form.getCount();
        Item item = new Item();
        item.setCost(form.getCost());
        item.setDiscountRate(form.getDiscountRate());
        item.setGoodsId(form.getId());
        item.setStatus(Item.STATUS_NORMAL);
        item.setMemo(form.getMemo());
        item.setPurchase(form.getPurchase());
        item.setTrade(form.getTrade());

        inventoryService.store(item, form.getStorehouseId(), count);
        status.setComplete();

        StoreForm buf = new StoreForm();
        buf.setBrandId(form.getBrandId());
        buf.setCategoryId(form.getCategoryId());
        buf.setId(form.getId());
        saveFormBuf(request, response, buf);
        String backURL = ParamUtils.getString(request, PARAM_BACK_URL, null);
        if (null != backURL) {
            return "redirect:" + backURL;
        } else {
            return "redirect:" + URI_LIST;
        }
    }

    @RequestMapping(value = INVENTORY_PREFIX + "/store/autosuggest", method = RequestMethod.GET)
    public
    @ResponseBody
    Map<String, ? extends Object> search(HttpServletResponse response) {

        response.setStatus(HttpServletResponse.SC_OK);

        Map<String, Object> modelMap = new HashMap<String, Object>();
        modelMap.put("brandList", getBrandList(null));

        return modelMap;
    }

    /**
     * 根据关键词获取商品列表<搜索商品>
     *
     * @param request
     * @param model
     * @return
     * @throws Exception
     * @see #list(HttpServletRequest, ModelMap)
     */
    private List<Goods> searchGoods(HttpServletRequest request, ModelMap model) throws Exception {
        String q = ParamUtils.getString(request, "q", null);
        if (q == null) {
            return null;
        }
        Pagination pagination = new Pagination(request, MAX_LIST);
        Result result = goodsSearcher.search(q, pagination);
        List<Goods> goodsList = (List<Goods>) result.getItems();
        if (ValidatorHelper.isNotEmpty(goodsList)) {
            for (Goods o : goodsList) {
                Goods goods = goodsService.getGoodsById(o.getId());
                BeanUtils.copyProperties(o, goods);
            }
        }
        int total = result.getTotal();
        pagination.setTotal(total);
        Map<String, Object> elements = new HashMap<String, Object>();
        elements.put("q", q);
        pagination.setElements(elements);
        PaginationHelper.setAttribute(request, pagination);
        model.put("q", result.getOrigiKey());
        return goodsList;
    }

    /**
     * 根据普通的GET请求获取商品列表
     *
     * @param request
     * @param model
     * @return
     * @see #list(HttpServletRequest, ModelMap)
     */
    private List<Goods> getGoodsList(HttpServletRequest request, ModelMap model) {
        List<Goods> goodsList = null;
        String categoryId = ParamUtils.getString(request, PARAM_CATEGORY_ID, null);
        String brandId = ParamUtils.getString(request, PARAM_BRAND_ID, null);
        Pagination pagination = new Pagination(request, MAX_LIST);
        pagination.setOrderList(new Pagination.Order[]{
                Pagination.getNewOrder("recently_update", Pagination.Order.DESCENDING)
        });
        Integer total = null;
        if (categoryId != null && brandId != null) {
            goodsList = goodsService.findByBrandIdAndCategoryId(brandId, categoryId, pagination);
            total = goodsService.countByBrandIdAndCategoryId(brandId, categoryId);
        } else if (categoryId != null) {
            goodsList = goodsService.findByCategoryId(categoryId, pagination);
            total = goodsService.countByCategoryId(categoryId);
        } else if (brandId != null) {
            goodsList = goodsService.findByBrandId(brandId, pagination);
            total = goodsService.countByBrandId(brandId);
        } else {
            goodsList = goodsService.findAllGoods(pagination);
            total = goodsService.countAll();
        }
        if (categoryId != null) {
            List<Properties> _props = goodsService.findPropsByCategoryId(categoryId);
            List<Prop> props = new ArrayList<Prop>();
            if (ValidatorHelper.isNotEmpty(_props)) {
                for (Properties properties : _props) {
                    Prop prop = new Prop();
                    BeanUtils.copyProperties(prop, properties);
                    List<PropValue> values = goodsService.findPropValues(prop.getId());
                    prop.setValues(values);
                    props.add(prop);
                }
            }
            model.put("props", props);
        }
        pagination.setTotal(total);
        Map<String, Object> elements = new HashMap<String, Object>();
        elements.put(PARAM_BRAND_ID, brandId);
        elements.put(PARAM_CATEGORY_ID, categoryId);
        pagination.setElements(elements);
        PaginationHelper.setAttribute(request, pagination);

        model.addAttribute(PARAM_BRAND_ID, brandId);
        model.addAttribute(PARAM_CATEGORY_ID, categoryId);

        return goodsList;
    }

    @RequestMapping(value = URI_LIST, method = RequestMethod.GET)
    public String list(HttpServletRequest request, ModelMap model) {
        //
        BackToURLUtils.setCurrentURLToAttr(request, PARAM_BACK_URL);

        List<Goods> goodsList = null;

        if (ValidatorHelper.isEmpty(ParamUtils.getStringParameter(request, "q"))) {
            goodsList = getGoodsList(request, model);
        } else {
            try {
                goodsList = searchGoods(request, model);
            } catch (Exception e) {
                LOG.error(e.toString());
                e.printStackTrace();
            }
        }
        //
        if (ValidatorHelper.isNotEmpty(goodsList)) {
            List<GoodsVO> voList = new ArrayList<GoodsVO>();
            copyGoodsToVOList(goodsList, voList);
            for (GoodsVO vo : voList) {
                List<GoodsPropValue> propValues = goodsService.findGoodsPropValueByGoodsId(vo.getId());
                vo.setPropValues(propValues);
            }
            model.addAttribute("goodsVOList", voList);
        }
        //
        //model.addAttribute("brandList", getBrandList(null));
        //model.addAttribute("categoryList", getCategoryList(null));
        return VIEW_LIST;
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/store/goodsSelector")
    public String showBrandAndCategory(HttpServletRequest request,
                                       ModelMap modelMap) {

        List<Category> categoryList = goodsService.findAllCategory();
        modelMap.put("categoryList", categoryList);

        List<Brand> brandList = goodsService.findAllBrand();
        modelMap.put("brandList", brandList);

        List<SellController.GoodsVO> voList = new ArrayList<SellController.GoodsVO>();
        String q = ParamUtils.getString(request, "q", null);
        String cid = ParamUtils.getString(request, "cid", null);
        String bid = ParamUtils.getString(request, "bid", null);
        if (ValidatorHelper.isEmpty(q)
                && ValidatorHelper.isEmpty(cid)
                && ValidatorHelper.isEmpty(bid)) {
            return "/admin/sell/brandAndCategory";
        } else if (ValidatorHelper.isNotEmpty(cid) || ValidatorHelper.isNotEmpty(bid)) {
            // 按照品牌和种类找商品
            Brand brand = goodsService.getBrandById(bid);
            Category category = goodsService.getCategoryById(cid);
            List<Goods> goodsList = goodsService.findByBrandIdAndCategoryId(bid, cid, null);
            for (Goods goods : goodsList) {
                SellController.GoodsVO vo = new SellController.GoodsVO();
                BeanUtils.copyProperties(vo, goods);
                vo.setBrand(brand);
                vo.setCategory(category);
                int c = inventoryService.countStatusNormalByGoodsId(goods.getId());
                vo.setInventoryCount(c);
                voList.add(vo);
            }
        } else {
            // 按关键词查找商品
            Pagination pagination = new Pagination(request, 100);
            try {
                Result result = goodsSearcher.search(q, pagination);
                pagination.setTotal(result.getTotal());
                if (result != null && result.getItems() != null) {
                    List<?> list = result.getItems();
                    for (Object rs : list) {
                        GoodsSearcher.GoodsVO g = (GoodsSearcher.GoodsVO) rs;
                        Goods goods = goodsService.getGoodsById(g.getId());
                        SellController.GoodsVO vo = new SellController.GoodsVO();
                        BeanUtils.copyProperties(vo, goods);
                        vo.setBrand(goodsService.getBrandById(goods.getBrandId()));
                        vo.setCategory(goodsService.getCategoryById(goods.getCategoryId()));
                        vo.setInventoryCount(inventoryService.countStatusNormalByGoodsId(goods.getId()));
                        voList.add(vo);
                    }
                }
            } catch (Exception e) {
                LOG.error(e.toString());
            }
        }
        modelMap.put("goodsVOList", voList);
        return "/admin/store/goodsList";
    }

    private void copyGoodsToVOList(List<Goods> goodsList, List<GoodsVO> voList) {
        for (Goods goods : goodsList) {
            GoodsVO vo = new GoodsVO();
            BeanUtils.copyProperties(vo, goods);
            //vo.setLatestStore(goods.getLatestStore());
            Category category = goodsService.getCategoryById(goods.getCategoryId());
            if (category != null) {
                vo.setCategoryName(category.getName());
            }

            Brand brand = goodsService.getBrandById(goods.getBrandId());
            if (brand != null) {
                vo.setBrandName(brand.getName());
            }

            int a = inventoryService.countStatusNormalByGoodsId(goods.getId());
            vo.setTotal(a);
            voList.add(vo);
        }
    }


    private List<Category> getCategoryList(String keys) {
        List<Category> categoryList = goodsService.findAllCategory();
        return categoryList;
    }

    private List<Brand> getBrandList(String keys) {
        List<Brand> brandList = goodsService.findAllBrand();
        return brandList;
    }

    private StoreForm getGoodsForm(HttpServletRequest request) {
        StoreForm form = null;
        String cid = ParamUtils.getString(request, PARAM_CATEGORY_ID, null);
        String bid = ParamUtils.getString(request, PARAM_BRAND_ID, null);
        String gid = ParamUtils.getString(request, PARAM_GOODS_ID, null);
        if (gid != null) {
            Goods goods = goodsService.getGoodsById(gid);
            if (goods != null) {
                form = new StoreForm();
                BeanUtils.copyProperties(form, goods);
                form.setBrand(goodsService.getBrandById(form.getBrandId()));
                form.setCategory(goodsService.getCategoryById(form.getCategoryId()));
            }
        } else if (ValidatorHelper.isNotEmpty(bid)
                || ValidatorHelper.isNotEmpty(cid)) {
            form = new StoreForm();
            form.setBrandId(bid);
            form.setCategoryId(cid);
        }
        /*else {
			String buf = HttpCookieUtils.getValue(request, "storeFormBuf", null);
			if(buf != null) {
				form = (StoreForm) JSONProvider.toBean(buf, StoreForm.class);
			}
		}*/
        if (form == null) {
            form = new StoreForm();
        }
        form.setAddTime(
                DateTimeUtils.format(
                        DateTimeUtils.now(), DateTimeUtils.FMT_YYYY_MM_DD_HH_MM_SS));
        return form;
    }

    private void saveFormBuf(HttpServletRequest request
            , HttpServletResponse response, StoreForm buf) {
        String json = JSONProvider.toJSON(buf);
        HttpCookieUtils.setValue(response, null, "storeFormBuf", json, 60 * 60 * 24);
    }

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsSearcher goodsSearcher;
    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private StorehouseService storehouseService;

    public static class Prop extends Properties {

        /**
         *
         */
        private static final long serialVersionUID = 4449458435510569867L;

        public List<PropValue> values;

        public List<PropValue> getValues() {
            return values;
        }

        public void setValues(List<PropValue> values) {
            this.values = values;
        }
    }

}
